package com.qk.management.statemachine.executor;

import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class StateMachineExecutor {

    public <S, E> StateMachineExecutionBuilder<S, E> withFactory(StateMachineFactory<S, E> factory) {
        return new StateMachineExecutionBuilder<>(factory);
    }

    public static class StateMachineExecutionBuilder<S, E> {
        private final StateMachineFactory<S, E> factory;
        private StateMachineListenerAdapter<S, E> listener;
        private String machineId;
        private S currentState;
        private E event;
        private final Map<String, Object> headers = new HashMap<>();
        private String entityIdKey;

        public StateMachineExecutionBuilder(StateMachineFactory<S, E> factory) {
            this.factory = factory;
        }

        public StateMachineExecutionBuilder<S, E> withListener(StateMachineListenerAdapter<S, E> listener) {
            this.listener = listener;
            return this;
        }

        public StateMachineExecutionBuilder<S, E> withMachineId(String machineId) {
            this.machineId = machineId;
            return this;
        }

        public StateMachineExecutionBuilder<S, E> withCurrentState(S currentState) {
            this.currentState = currentState;
            return this;
        }

        public StateMachineExecutionBuilder<S, E> withEvent(E event) {
            this.event = event;
            return this;
        }

        public StateMachineExecutionBuilder<S, E> withHeader(String key, Object value) {
            this.headers.put(key, value);
            return this;
        }

        public StateMachineExecutionBuilder<S, E> withHeaders(Map<String, Object> headers) {
            this.headers.putAll(headers);
            return this;
        }

        public boolean execute() {
            StateMachine<S, E> stateMachine = factory.getStateMachine(machineId);

            if (listener != null) {
                stateMachine.addStateListener(listener);
            }
            // 重置状态机到指定状态
            stateMachine.getStateMachineAccessor().doWithAllRegions(access -> {
                access.resetStateMachine(new DefaultStateMachineContext<>(currentState, null, null, null));
            });

            stateMachine.start();

            Message<E> message = MessageBuilder.withPayload(event)
                    .copyHeaders(headers)
                    .build();
            boolean result = stateMachine.sendEvent(message);
            System.out.println("事件接受结果: " + result);
            System.out.println("当前状态: " + stateMachine.getState().getId());
            return result;
        }
    }
}